import { Injectable } from "@nestjs/common";
import { CacheRedisService } from "src/cache-redis/cache-redis.service";
import { InjectRepository } from "@nestjs/typeorm";
import { Room } from "src/entity/room.entity";
import { Repository } from "typeorm";
import {
  getKwRandSong,
  searchKwSong,
  kwSongItem,
  getKwSongLrc,
  wsSongItem,
  getKwSongUrl,
} from "./kuwo";
import { error, getRandomInt, getTimeStamp, success } from "src/utils/common";
import { url } from "inspector";

@Injectable()
export class SongService {
  constructor(
    private redis: CacheRedisService,
    @InjectRepository(Room) private room: Repository<Room>
  ) {}

  async execute(): Promise<{ room_id: number; song: any }[]> {
    const rooms = await this.getRoomList();
    if (rooms.length === 0) {
      return [];
    }
    const arr = [];
    for (let index = 0; index < rooms.length; index++) {
      const room = rooms[index];
      //获取当前房间播放的歌曲
      const song = await this.getNowPlayingSong(room.room_id);

      //进行缓存
      if (song) {
        //歌曲是否过期
        if (getTimeStamp() < song.song.duration + song.time) {
          //缓存下一首
          await this.preLoadMusicUrl(room);
          continue;
        }
      }
      //当前播放 播放
      let songNow = await this.updateSongQueu(room.room_id);

      if (!songNow) {
        songNow = await this.getRandSong();
      }
      arr.push({ room_id: room.room_id, song: songNow });
      //设置缓存
      this.palySong(room.room_id, songNow);
    }
    return arr;
  }

  async updateSongQueu(room_id: number): Promise<wsSongItem> {
    const songs =
      (await this.redis.get<wsSongItem[]>(room_id.toString())) ?? [];
    if (songs.length) {
      const songNow = songs[0];
      songNow.time = getTimeStamp() + 5;
      songs.shift();
      this.redis.set(`SongList_${room_id}`, songs, 86400);
      return songNow;
    }
  }

  //缓存
  async preLoadMusicUrl(room: Room): Promise<kwSongItem[] | boolean> {
    const preRoomId = room.room_id;
    const songList = await this.getSongList(preRoomId);
    let song: wsSongItem;
    //如果当前队列有值则不进行缓存
    if (songList.length) {
      song = songList[0];
    } else {
      song = await this.getRandSong();
      if (song) {
        this.addSongToList(preRoomId, {
          song: song.song,
          time: getTimeStamp(),
        });
      }
    }
    if (!song) {
      return false;
    }
    const preRid = song.song.rid;
    if (preRid) {
      //获取当前key是否存在
      let preSong = await this.redis.get(`song_play_temp_url_${preRid}`);
      let preCount = (await this.redis.get(`song_pre_load_count`)) ?? 0;
      if (!preSong && preCount < 5) {
        await this.redis.set(`song_pre_load_count`, preCount + 1, 60);
        const preUrl = await getKwSongUrl(preRid);
        if (url) {
          await this.redis.set(`song_play_temp_url_${preRid}`, preUrl, 3600);
        }
      }
    }
  }

  /**
   * 获取当前房间歌曲列表
   *
   * @param room_id 房间id
   * @returns  返回当前redis中的歌曲
   */
  async getSongList(room_id: number): Promise<wsSongItem[]> {
    return (await this.redis.get(`SongList_${room_id}`)) ?? [];
  }

  /**
   * 把歌曲添加进redis中
   * @param room_id 房间id {number}
   * @param song 歌曲信息
   */

  async addSongToList(room_id: number, song: wsSongItem) {
    //判断当前歌曲在队列中是否存在
    const songList =
      (await this.redis.get<wsSongItem[]>(`SongList_${room_id}`)) ?? [];
    if (song) {
      songList.push(song);
    }
    this.redis.set(`SongList_${room_id}`, songList);
  }

  /**
   * 用于查询房间id
   *
   * @returns 全部房间id
   */
  async getRoomList() {
    let rooms = await this.redis.get<Room[]>("RoomList");
    if (!rooms) {
      rooms = await this.room.find({ select: ["room_id"] });
      this.redis.set("RoomList", rooms);
    }
    return rooms;
  }

  /**
   * 随机点歌
   */
  async getRandSong(): Promise<wsSongItem | null> {
    const bangIdArray = [
      278, 284, 26, 64, 187, 281, 153, 17, 16, 158, 145, 93, 185, 290, 279, 264,
      283, 282, 255,
    ];
    //随机点歌的歌曲
    const res = await getKwRandSong(
      bangIdArray[getRandomInt(bangIdArray.length)]
    );
    if (res) {
      return res;
    }
    return null;
  }

  async palySong(room_id: number, song: wsSongItem) {
    if (song === null) {
      return;
    }
    this.redis.set(`SongNow_${room_id}`, song, 3600);
    this.redis.set(`song_detail_${song.song.rid}`, song.song, 3600);
  }

  /**
   *
   * @param room_id 房间id
   * @returns 获取现在正在播放的歌曲
   */
  getNowPlayingSong(room_id: number): Promise<wsSongItem> {
    return this.redis.get(`SongNow_${room_id}`);
  }

  /**
   *
   * @param room_id 房间id
   * @param rid 歌曲id
   */
  async addSong(room_id: number, rid: number, user: any) {
    //判断房间是否存在
    const room = await this.room.findOne({ where: { room_id } });
    if (!room) {
      return error("房间不存在");
    }
    //查询缓存中是否存在歌曲信息
    let song = await this.redis.get(`song_detail_${rid}`);
    if (!song) {
      return error("暂时没有歌曲");
    }
    this.addSongToList(room_id, song);
    return success("点歌成功");
  }

  /**
   *
   * @param keyword 需要搜索的内容
   * @returns
   */
  async searchSong(keyword: string): Promise<kwSongItem[]> {
    //通过kw去查找歌曲
    const songList = await searchKwSong(keyword);
    const arr = [];
    if (songList.length) {
      for (let index = 0; index < songList.length; index++) {
        const song = songList[index];
        const { rid, artist, name, pic, musicrid, duration } = song;
        const temp = { rid, artist, name, pic, musicrid, duration };
        await this.redis.set(`song_detail_${song.rid}`, temp, 0);
        arr.push(temp);
      }
    }
    return arr;
  }

  /**
   *
   * @param rid 歌曲id
   * @returns
   */
  getSongLrc(rid: number): Promise<{ lrclist: [] }> {
    return getKwSongLrc(rid);
  }

  async getSongUrl(rid: number): Promise<string> {
    return await getKwSongUrl(rid);
  }
}
